package javdoku;

import java.security.SecureRandom;

public class SudokuBoard {
	private int[][] grid;
	private SecureRandom r;
	public SudokuBoard(){
        grid = new int[9][9];
        for (int i=0; i<9; i++)
            for (int j=0; j<9; j++)
                grid[i][j]=0;
        r = new SecureRandom();
        r.nextInt(); //seeds so there is no delay on first board creation
	}
    private boolean isPlaceGood(int r, int c, int v){
        if (v>9)
            return false;
        for (int i=0; i<c; i++)
            if (grid[r][i]==v)
                return false;
        for (int i=0; i<r; i++)
            if (grid[i][c]==v)
                return false;
        if (r%3!=0){
            if (r%3==1){
                for (int i=(c-(c%3)); i<(c-(c%3)+3); i++)
                    if (grid[r-1][i]==v)
                        return false;
            }
            else{
                for (int k=(r-(r%3)); k<r; k++)
                    for (int j=(c-(c%3)); j<(c-(c%3)+3); j++)
                        if (grid[k][j]==v)
                            return false;
            }
        }
        return true;
    }
    private void setPlace(int row, int col, int val){
        grid[row][col]=val;
    }
     public void printBoard(int[][] board){
        for(int i=0; i<9; i++){
            if (i==3 || i==6)
                System.out.println();
            for(int j=0; j<9; j++){
                if (j%3==0)
                    System.out.print(' ');
                System.out.print(board[i][j]);
            }
            System.out.println();
        }
        System.out.println();
     }
     private boolean allTrue(boolean x[][][], int r, int c){
    	 for (int i=0; i<9; i++)
    		 if (x[r][c][i]==false)
    			 return false;
    	 return true;
     }
     public int[][] makeBoards(int amt){
        //assert amt>0,'The number of boards must be at least one.'
        grid = new int[9][9];
        for (int i=0; i<9; i++){
            for (int j=0; j<9; j++)
                grid[i][j]=0;
        }
        /*self.t = time.time()
        self.fOut='SudokuBoards'+str(amt)+'.txt'
        self.file=open(self.fOut, 'w')*/
        int num=0;
        int row=0;
        int col=0;
        int val=1;
        while ((row < 9) && (col < 9) && (row>-1) && (num<amt)){
            //self._printBoard()
            while (!isPlaceGood(row, col, val) && (row>-1)){
                //printBoard(); 
                if (val>=9){
                    setPlace(row, col, 0);
                    col--;
                    if (col<0 && row>0){
                        row--;
                        col=8;
                    }
                    val=grid[row][col]+1;
                    /*if self.col > 0:
                        self.col-=1
                        self.val = self.grid[self.row][self.col]+1
                    elif self.col == 0 and self.row > 0:
                        self.col=8
                        self.row-=1
                        self.val = self.grid[self.row][self.col]+1
                    else:
                        self.row=9*/
                }
                
                if (val<9)
                    val++;
            }
            setPlace(row, col, val);
            //print(self.row, self.col, self.val)
            if (col == 8 && row == 8){
                //made board
                num++;
                //writeBoard(file, num);
                val++;
                //if (num%1000==0)
                    //System.out.println(num);
            }
            else if (col < 8){
                col++;
                val=1;
            }
            else if (row < 8){
                col=0;
                row++;
                val=1;
            }
        }
        return grid;
     }
        //self.file.close()
        //self.t=time.time()-self.t
        //print('Generating '+str(amt)+' board' + ('s' if amt>1 else '')+' took '+str(self.t)+' seconds, '+str(self.t/60)+' minutes, or '+str(self.t/3600)+' hours.')
    public int[][] randBoards(int amt){
        //assert amt>0,'The number of boards must be at least one.'
        grid = new int[9][9];
        for (int i=0; i<9; i++)
            for (int j=0; j<9; j++)
                grid[i][j]=0;
        //self.t = time.time()
        //self.fOut='RandomSudokuBoards'+str(amt)+'.txt'
        //self.file=open(self.fOut, 'w')
        int num=0;
        int row=0;
        int col=0;
        int val=r.nextInt(9);
        boolean[][][] tries = new boolean[9][9][9];
        
        for (int i=0; i<9; i++){
        	for (int j=0; j<9; j++)
        		for (int k=0; k<9; k++)
        			tries[i][j][k]=false;
        }
        while ((row < 9) && (col < 9) && (row>-1) && num<amt){
            while ((!isPlaceGood(row, col, val+1)) && (row>-1)){
                //printBoard();
                //if (tries[row][col][val]=false){
                tries[row][col][val]=true;
                //}
                if (allTrue(tries, row, col)){
                    setPlace(row, col, 0);
                    for (int i=0; i<9; i++)
                    	tries[row][col][i]=false;
                    col--;
                    val=r.nextInt(9);
                    if ((col<0) && (row>0)){
                        row--;
                        col=8;
                    }
                    //self.val=random.randrange(1,10)
                    /*if self.col > 0:
                        self.col-=1
                        self.val = self.grid[self.row][self.col]+1
                    elif self.col == 0 and self.row > 0:
                        self.col=8
                        self.row-=1
                        self.val = self.grid[self.row][self.col]+1
                    else:
                        self.row=9*/
                }
                if (!allTrue(tries, row, col)){
                    while (tries[row][col][val])
                    	val=r.nextInt(9);
                    //tries[row][col][val]=true;
                }
            }
            setPlace(row, col, val+1);
            if (tries[row][col][val]==false)
                    tries[row][col][val]=true;
            //self._printBoard()
            //print(self.row, self.col, self.val)
            if (col == 8 && row == 8){
                //made board
                num++;
                return grid;
                //self._writeBoard(self.file, self.num)
                //self.grid=list()
                /*grid = new int[9][9];
                for (int i=0; i<9; i++)
                    for (int j=0; j<9; j++)
                        grid[i][j]=0;
                tries = new boolean[9][9][9];
                
                for (int i=0; i<9; i++){
                	for (int j=0; j<9; j++)
                		for (int k=0; k<9; k++)
                			tries[i][j][k]=false;
                }
                row = 0;
                col = 0;
                if (num%1000==0)
                     System.out.println(num);*/
            }
            else if (col < 8){
                col++;
            }
            else if (row < 8){
                col=0;
                row++;
            }
            tries[row][col][val]=true;
            val=r.nextInt(9);
        }
        //self.file.close()
        //self.t=time.time()-self.t
        //print('Generating '+str(amt)+' board' + ('s' if amt>1 else '')+' took '+str(self.t)+' seconds, '+str(self.t/60)+' minutes, or '+str(self.t/3600)+' hours.')
        return grid;
    }
}